﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace HelloMods
{
    class SettingsPanel : MonoBehaviour
    {
        private Modding.ILogger logger = null;

        private bool showSettings = false;
        private GameObject canvasObject;
        private AssetBundle asset;
        private Settings settings = Settings.Instance;

        void Start()
        {
            this.logger = HelloMod.LoadedInstance;

            init();
        }

        private void init()
        {
            try
            {
                clear();

                logger.Log($"now load settings panel! version: {Application.unityVersion}");
                var path = Path.Combine(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location),
                    "settings.prefab").Replace("\\", "/");
                logger.Log("load settings panel from:" + path);
                this.asset = AssetBundle.LoadFromFile(path);

                var obj = asset.LoadAsset<GameObject>("Assets/Settings.prefab");


                this.canvasObject = GameObject.Instantiate(obj);

                this.canvasObject.transform.SetParent(this.transform);
                this.canvasObject.SetActive(showSettings = false);
                //this.canvasObject.layer = LayerMask.NameToLayer("uGUI");
                //var cvs = this.canvasObject.GetComponent<Canvas>();
                //cvs.sortingLayerID = 999;
                //cvs.sortingOrder = 100;


                regToggle("toggle_switch", settings.Enabled, p => settings.Enabled = p);
                regToggle("toggle_showHealth", settings.ShowHealth, p => settings.ShowHealth = p);
                regToggle("toggle_infinityMP", settings.InfinityMP, p => settings.InfinityMP = p);
                regToggle("toggle_infinityJump", settings.InfinityJump, p => settings.InfinityJump = p);
                regSlider("slider_attack", settings.Attack, p => settings.Attack = p);
                regSlider("slider_takeDamage", settings.TakeDamage, p => settings.TakeDamage = p);
                regSlider("slider_takeHealth", settings.TakeHealth, p => settings.TakeHealth = p);
                regSlider("slider_addGeo", settings.AddGeo, p => settings.AddGeo = p);
                regSlider("slider_jumpSpeed", settings.JumpSpeed, p => settings.JumpSpeed = p);
                regSlider("slider_nailScale", settings.NailScale, p => settings.NailScale = p);
                logger.Log("success");
            }
            catch (Exception ex)
            {
                logger.LogError("init error:" + ex);
            }


        }

        private void clear()
        {
            try
            {
                if (canvasObject != null)
                {
                    GameObject.Destroy(this.canvasObject);
                    this.asset.Unload(true);
                    this.canvasObject = null;
                    this.asset = null;
                    logger.Log($"clear ok!");
                }
            }
            catch (Exception ex)
            {
                logger.LogError("clear error:" + ex);
            }
        }

        void OnDisable()
        {
            clear();
        }

        void OnDestroy()
        {
            clear();
        }


        void Update()
        {
            var gm = GameManager.instance;


            if (Input.GetKeyDown(KeyCode.Home))
            {
                if (GameManager.instance.gameState == GlobalEnums.GameState.PLAYING)
                {
                    showSettings = !showSettings;
                    var es = GameObject.Find("EventSystem");
                    var c2 = es.GetComponent<InControl.HollowKnightInputModule>();
                    c2.ActivateModule();
                    c2.allowMouseInput = true;
                }

                if (this.canvasObject)
                {
                    this.canvasObject.SetActive(showSettings);
                }


                gm.isPaused = showSettings;
                Time.timeScale = gm.isPaused ? 0 : 1;
            }
        }


        void regToggle(string name, bool value, Action<bool> cb)
        {
            var obj = this.canvasObject.FindChild(p => p.name == name).FirstOrDefault();
            var toggle = obj.GetComponent<Toggle>();

            toggle.onValueChanged.AddListener(p =>
            {
                logger.LogError($"{name},value:{p}");
                cb(p);
            });
            toggle.isOn = value;
        }

        void regSlider(string name, float value, Action<float> cb)
        {
            var obj = this.canvasObject.FindChild(p => p.name == name).FirstOrDefault();
            var objValue = this.canvasObject.FindChild(p => p.name == name + "_value").FirstOrDefault();
            var toggle = obj.GetComponent<Slider>();
            var indaitor = objValue.GetComponent<Text>();

            toggle.onValueChanged.AddListener(p =>
            {
                var scale = p * 0.1f;
                if (indaitor != null)
                    indaitor.text = scale.ToString("0.0");
                cb(scale);
            });
            toggle.value = value * 10;
        }

    }

    public class Node
    {
        public Node(GameObject g)
        {
            this.N = g.name;
            this.T = g.tag;
            this.C = g.GetType().FullName;
            this.A = g.activeSelf;
            this.D = g.ToString();
            this.Hash = g.GetHashCode();
            this.Layer = g.layer + "_" + LayerMask.LayerToName(g.layer);
            this.Coms = g.GetComponents<UnityEngine.Component>()
                 .Select(p => new Com(p)).ToList();
            var p = g.transform.parent;
            while (p != null)
            {
                F = p.gameObject.name + "/" + F;
                p = p.parent;
            }
        }

        public string F { get; } = "";

        public string N { get; }

        public string T { get; set; }

        public string C { get; }

        public bool A { get; }

        public string D { get; }

        public int Hash { get; }

        public string Layer { get; }

        public List<Com> Coms { get; } = new List<Com>();

    }

    public class Com
    {
        public Com(Component c)
        {
            this.C = c.GetType().FullName;
            this.D = c.ToString();
        }

        public string C { get; set; }

        public string D { get; set; }

        //    public bool Enabled { get; set; }
    }
}
